package nacos

import (
	"context"
	"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/v2/model"
	"github.com/nacos-group/nacos-sdk-go/v2/vo"
	"google.golang.org/grpc/resolver"
	"time"
)

type NacosBuilder struct {
	Client      naming_client.INamingClient
	ServiceName string
}

type selectFn func(client naming_client.INamingClient, service string) ([]model.Instance, error)

func (b *NacosBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
	ctx, cancel := context.WithCancel(context.Background())
	nacosResolver := &NacosResolver{cancelFunc: cancel, ticker: time.NewTicker(time.Second * 10)}
	pipe := make(chan []resolver.Address)
	nacosResolver.pipe = pipe
	nacosResolver.cc = cc
	nacosResolver.ctx = ctx
	go b.Client.Subscribe(&vo.SubscribeParam{
		ServiceName:       b.ServiceName,
		SubscribeCallback: nacosResolver.callBackHandle, // required
	})

	nacosResolver.wg.Add(1)
	go nacosResolver.populateEndpoints()
	nacosResolver.wg.Add(1)
	go nacosResolver.selectInstances(b.selectInstanceFn())

	return nacosResolver, nil
}

func (b *NacosBuilder) selectInstanceFn() func() ([]model.Instance, error) {
	return func() ([]model.Instance, error) {
		return b.Client.SelectInstances(vo.SelectInstancesParam{
			ServiceName: b.ServiceName,
			HealthyOnly: true,
		})
	}
}

func (b *NacosBuilder) Scheme() string {
	return "nacos"
}
